//! # 限流策略实现
//!
//! 提供多种限流策略的具体实现

use super::{RateLimitStrategy, RateLimitConfig, RateLimitStrategyType, RequestContext};
use async_trait::async_trait;
use std::time::Duration;

/// 基于IP的限流策略
pub struct IpBasedStrategy {
    config: RateLimitConfig,
}

impl IpBasedStrategy {
    pub fn new(config: RateLimitConfig) -> Self {
        Self { config }
    }
}

#[async_trait]
impl RateLimitStrategy for IpBasedStrategy {
    async fn get_key(&self, context: &RequestContext) -> String {
        format!("ip:{}", context.client_ip.map_or("unknown".to_string(), |ip| ip.to_string()))
    }

    async fn get_config(&self, _context: &RequestContext) -> RateLimitConfig {
        self.config.clone()
    }

    fn get_strategy_type(&self) -> RateLimitStrategyType {
        RateLimitStrategyType::IpBased
    }

    fn get_strategy_name(&self) -> &str {
        "ip_based"
    }
}

/// 基于用户的限流策略
pub struct UserBasedStrategy {
    config: RateLimitConfig,
}

impl UserBasedStrategy {
    pub fn new(config: RateLimitConfig) -> Self {
        Self { config }
    }
}

#[async_trait]
impl RateLimitStrategy for UserBasedStrategy {
    async fn get_key(&self, context: &RequestContext) -> String {
        format!("user:{}", context.user_id.as_deref().unwrap_or("anonymous"))
    }

    async fn get_config(&self, _context: &RequestContext) -> RateLimitConfig {
        self.config.clone()
    }

    fn get_strategy_type(&self) -> RateLimitStrategyType {
        RateLimitStrategyType::UserBased
    }

    fn get_strategy_name(&self) -> &str {
        "user_based"
    }
}

/// 基于路径的限流策略
pub struct PathBasedStrategy {
    config: RateLimitConfig,
}

impl PathBasedStrategy {
    pub fn new(config: RateLimitConfig) -> Self {
        Self { config }
    }
}

#[async_trait]
impl RateLimitStrategy for PathBasedStrategy {
    async fn get_key(&self, context: &RequestContext) -> String {
        format!("path:{}", context.path)
    }

    async fn get_config(&self, _context: &RequestContext) -> RateLimitConfig {
        self.config.clone()
    }

    fn get_strategy_type(&self) -> RateLimitStrategyType {
        RateLimitStrategyType::PathBased
    }

    fn get_strategy_name(&self) -> &str {
        "path_based"
    }
}